Skip to content

boot: boot_serial: add raw (non-console) SMP recovery protocol#4

Open
JPHutchins wants to merge 1 commit into
mainfrom
feature-serial-raw-smp
Open

boot: boot_serial: add raw (non-console) SMP recovery protocol#4
JPHutchins wants to merge 1 commit into
mainfrom
feature-serial-raw-smp

Conversation

@JPHutchins
Copy link
Copy Markdown
Collaborator

@JPHutchins JPHutchins commented Jun 1, 2026

Summary

Adds raw (non-console) SMP support to mcuboot serial recovery (the bootloader-side SMP server), mirroring Zephyr's CONFIG_UART_MCUMGR_RAW_PROTOCOL so the same raw mcumgr client can talk to both the application and the bootloader.

With BOOT_SERIAL_RAW_PROTOCOL, the SMP packet (nmgr_hdr + payload) is exchanged as plain binary instead of the SMP over console encoding — no base64, no two-byte length prefix, no CRC16, no SHELL_NLIP framing, no \n. Packet boundaries are derived from the length field of the SMP header, so the encoding is transport-agnostic (UART, CDC ACM, CAN, RTT, …) and only needs a binary-capable link. The two encodings are mutually exclusive and selected at build time; in raw mode the base64 and CRC code and libraries are dropped.

Because raw framing has no CRC or delimiter to detect a truncated packet, BOOT_SERIAL_RAW_PROTOCOL_INPUT_TIMEOUT (enabled by default with the raw protocol; …_INPUT_TIMEOUT_MS default 3000) discards a partially received packet after a period without new data so a stalled or malformed transfer cannot permanently wedge recovery — mirroring Zephyr's CONFIG_MCUMGR_TRANSPORT_RAW_UART_INPUT_TIMEOUT.

Changes

  • boot_serial.c — raw TX in boot_serial_output; console-only boot_serial_in_dec/dec_buf #ifdef'd out in raw mode; new boot_serial_input_raw() that drains every complete packet from the receive buffer (by SMP-header length) and preserves the residue; input-expiration timeout in boot_serial_read_console.
  • serial_adapter.c#ifdef-gated raw paths; binary-safe byte collection (no \n split); console_read_raw() retains an unconsumed fragment tail across calls instead of truncating.
  • Kconfig.serial_recoveryBOOT_SERIAL_RAW_PROTOCOL plus …_INPUT_TIMEOUT / …_INPUT_TIMEOUT_MS; BASE64/CRC selected only for the console encoding.
  • mcuboot_config.hCONFIG_MCUBOOT_* macro mappings.
  • sample.yamlsample.bootloader.mcuboot.serial_recovery_raw Twister entry so the raw config is built in CI.
  • Docsserial_recovery.md + release note; serial_recovery_raw.conf sample fragment.

Verification

Built for nrf52840dk/nrf52840 (Zephyr 4.4.0, SDK 0.17.4, -Werror -Wall -Wextra) across the config matrix — raw (timeout on / off), raw + WAIT_FOR_DFU, and console — all compile clean and link:

  • Console encoding is byte-identical to before this change (no regression).
  • Raw with the timeout disabled is byte-identical to raw without the timeout feature (clean #ifdef-out, zero cost when off).
  • Raw mode saves ~1 KiB flash and ~1 KiB RAM vs console (the default-on timeout adds ~176 B flash), matching the Zephyr PR's reported win.

Reviewed across multiple passes; fixes applied for multi-packet residue handling, the boot_serial_output raw guard, and a fragment-truncation data-loss path.

Note: this is build-verified. Functional client↔server transfer testing belongs upstream in Zephyr tests/boot/with_mcumgr/, alongside where the mirrored Zephyr PR added its own transport_raw_uart test.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 1, 2026 23:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a build-time-selectable raw SMP transport (BOOT_SERIAL_RAW_PROTOCOL) to mcuboot's serial recovery, mirroring Zephyr's CONFIG_UART_MCUMGR_RAW_PROTOCOL. In raw mode the SMP header + payload is exchanged as plain binary (no base64, length prefix, CRC16, NLIP framing or \n); packet boundaries come from the SMP header nh_len. The console encoding remains the default; the two modes are mutually exclusive and the base64/CRC libraries are dropped in raw mode.

Changes:

  • New raw TX path in boot_serial_output plus a boot_serial_input_raw reassembler that drains complete packets and keeps residue, with the legacy console decode path #ifdef-gated.
  • serial_adapter.c gains a binary-safe ISR path (no \n split, end-of-IRQ fragment flush) and a console_read_raw reader that retains an unconsumed fragment tail across calls.
  • New BOOT_SERIAL_RAW_PROTOCOL Kconfig (conditionally selects BASE64/CRC), CONFIG_MCUBOOT_SERIAL_RAW_PROTOCOL mapping, a serial_recovery_raw.conf sample, plus docs and a release note.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
boot/boot_serial/src/boot_serial.c Raw TX in boot_serial_output; gates console decode; adds boot_serial_input_raw and raw branch in the read loop.
boot/zephyr/serial_adapter.c Binary-safe ISR fragment delivery and console_read_raw with persistent pending-tail.
boot/zephyr/Kconfig.serial_recovery Adds BOOT_SERIAL_RAW_PROTOCOL; makes BASE64/CRC conditional.
boot/zephyr/include/mcuboot_config/mcuboot_config.h Maps CONFIG_BOOT_SERIAL_RAW_PROTOCOL to MCUBOOT_SERIAL_RAW_PROTOCOL.
boot/zephyr/serial_recovery_raw.conf Sample Kconfig fragment for raw mode.
docs/serial_recovery.md Documents the new transport encoding option.
docs/release-notes.d/serial-recovery-raw-protocol.md Release note for the new option.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JPHutchins JPHutchins force-pushed the feature-serial-raw-smp branch from 77bf50c to acbf7d0 Compare June 1, 2026 23:48
Comment thread boot/zephyr/serial_adapter.c Outdated
Comment thread boot/zephyr/serial_adapter.c Outdated
Comment thread boot/zephyr/serial_adapter.c Outdated
Copy link
Copy Markdown
Collaborator Author

@JPHutchins JPHutchins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few cleanups to make the diff better

@JPHutchins JPHutchins force-pushed the feature-serial-raw-smp branch from acbf7d0 to 0c95767 Compare June 2, 2026 00:07
Add the BOOT_SERIAL_RAW_PROTOCOL option, which exchanges SMP packets
over the serial port as raw binary instead of the SMP-over-console
encoding: no base64, no two-byte length prefix, no CRC16 and no
SHELL_NLIP framing. Packet boundaries are derived from the length field
of the SMP header, so the encoding is transport-agnostic (UART, CDC ACM,
CAN, ...) and only requires a binary-capable link. The mcumgr client
must be configured to use a matching raw transport.

This mirrors Zephyr's CONFIG_UART_MCUMGR_RAW_PROTOCOL. The two encodings
are mutually exclusive and selected at build time; in raw mode the
base64 and CRC code and libraries are dropped, saving roughly 1 KiB of
flash and 1 KiB of RAM and increasing transfer speed.

Because the raw encoding has no CRC or framing to detect a truncated
packet, also add BOOT_SERIAL_RAW_PROTOCOL_INPUT_TIMEOUT (enabled by
default with the raw protocol): a partially received packet is dropped
after BOOT_SERIAL_RAW_PROTOCOL_INPUT_TIMEOUT_MS without new data so a
stalled transfer cannot wedge recovery. This mirrors Zephyr's
CONFIG_MCUMGR_TRANSPORT_RAW_UART_INPUT_TIMEOUT.

A serial_recovery_raw.conf fragment and a matching Twister build test
(sample.bootloader.mcuboot.serial_recovery_raw) are added so the raw
configuration is built in CI.

Signed-off-by: JP Hutchins <jp@intercreate.io>
Assisted-By: Claude:opus-4.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants